
/*
 * =========================================================================
 *
 *       FileName:  bhash.cpp
 *
 *    Description:
 *
 *        Version:  1.0
 *        Created:  2021-10-27 20:57:04
 *  Last Modified:  2021-10-27 21:25:37
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  zt ()
 *   Organization:
 *
 * =========================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include <iostream>
#include <memory>
#include <algorithm>
#include <vector>
#include <thread>
#include <mutex>
#include <map>
#include <list>
#include <string>
#include <functional>

using namespace std;

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>


struct person
{
    char* name;
    int age;
};

struct store_person
{
    struct person* per;
    struct store_person* next;
    char* key;
    int nHashA;
    int nHashB;
};

struct store_person* stuff;


#define HX (20)
#define HY (5)
#define MAX_NUM (HX*HY)
unsigned long cryptTable[MAX_NUM]; //1280

void prepareCryptTable()
{
    unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;

    for ( index1 = 0; index1 < HX; index1++ )
    {
        for ( index2 = index1, i = 0; i < HY; i++, index2 += HX )
        {
            unsigned long temp1, temp2;
            seed = ( seed * 125 + 3 ) % 0x2AAAAB;
            temp1 = ( seed & 0xFFFF ) << 0x10;
            seed = ( seed * 125 + 3 ) % 0x2AAAAB;
            temp2 = ( seed & 0xFFFF );
            cryptTable[index2] = ( temp1 | temp2 );
        }
    }
}

unsigned long HashString ( char* keystr, unsigned long dwHashType )
{
    unsigned char* key  = ( unsigned char* ) keystr;
    unsigned long seed1 = 0x7FED7FED;
    unsigned long seed2 = 0xEEEEEEEE;
    int ch;

    while ( *key != 0 )
    {
        ch = toupper ( *key++ );
        seed1 = cryptTable[ ( dwHashType << 8 ) + ch] ^ ( seed1 + seed2 );
        seed2 = ch + seed1 + seed2 + ( seed2 << 5 ) + 3;
    }

    return seed1;
}


int GetHashTablePos ( char* key, struct store_person* per )
{
    const int  HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;
    int  nHash = HashString ( key, HASH_OFFSET ) % MAX_NUM;
    int  nHashA = HashString ( key, HASH_A ) % MAX_NUM;
    int  nHashB = HashString ( key, HASH_B ) % MAX_NUM;
    printf ( "nHash ==%d\n", nHash );

    while ( per[nHash].key )
    {
        if ( per[nHash].nHashA == nHashA
                &&  per[nHash].nHashB == nHashB )
        {
            return nHash;
        }
        else
        {
            nHash = ( nHash + 1 ) % MAX_NUM;
        }
    }

    return -1;
}

void hash_set ( char* keystr, struct person* per )
{
    const int  HASH_OFFSET = 0, HASH_A = 1, HASH_B = 2;
    int  nHash = HashString ( keystr, HASH_OFFSET ) % MAX_NUM;
    int  nHashA = HashString ( keystr, HASH_A ) % MAX_NUM;
    int  nHashB = HashString ( keystr, HASH_B ) % MAX_NUM;
    struct store_person* store = &stuff[nHash];

    if ( store->key == NULL )
    {
        store->key = keystr;
        store->per = per;
        store->nHashA = nHashA;
        store->nHashB = nHashB;
        printf ( "store ok ,position is %d\n", nHash );
        return;
    }
}
int hash_get ( char* key, struct store_person* per )
{
    return GetHashTablePos ( key, per );
}

int main ( int argc, char* argv[] )
{
    ( void ) argc;
    ( void ) argv;
    prepareCryptTable();
    stuff = ( struct store_person* ) malloc ( sizeof ( struct store_person ) * MAX_NUM );

    if ( stuff == NULL )
        return -1;

    struct person pvalue1;
    pvalue1.name = "haha";
    pvalue1.age = 18;
    hash_set ( "key1", &pvalue1 );
    struct person pvalue2;
    pvalue2.name = "xixi";
    pvalue2.age = 20;
    hash_set ( "key2", &pvalue2 );
    struct person pvalue3;
    pvalue3.name = "lala";
    pvalue3.age = 12;
    hash_set ( "key3", &pvalue3 );
    struct person pvalue4;
    pvalue4.age = 16;
    hash_set ( "zt", &pvalue4 );
    struct person pvalue5;
    pvalue5.age = 14;
    hash_set ( "zt2", &pvalue5 );
    int pos = hash_get ( "key2", stuff );
    printf ( "pos is %d\n", pos );
    printf ( "person name ->%s, person age ->%d\n", stuff[pos].per->name, stuff[pos].per->age );
    return 0;
}

